package com.aorise.service.diagnosis.impl;

import com.aorise.exception.ServiceException;
import com.aorise.mapper.diagnosis.*;
import com.aorise.model.diagnosis.*;
import com.aorise.service.camera.CameraGroupService;
import com.aorise.service.diagnosis.DiagnosisPlanService;
import com.aorise.utils.ConstDefine;
import com.aorise.utils.StatusDefine;
import com.aorise.utils.StatusDefineMessage;
import com.aorise.utils.page.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author:cat
 * @Desicription: 诊断任务接口服务实现类
 * @Date:Created in 2019-06-24
 * @Modified By:
 */
@Service
public class DiagnosisPlanServiceImpl implements DiagnosisPlanService {

    @Autowired
    private DiagnosisPlanMapper  diagnosisPlanMapper;
    @Autowired
    private PlanCameraMapper     planCameraMapper;
    @Autowired
    private DiagnosisParamMapper diagnosisParamMapper;
    @Autowired
    private CameraGroupService   cameraGroupService;
    @Autowired
    private DiagnosisMQMapper diagnosisMQMapper;

    /**
     * @Author:cat
     * @Description 查询所有自动诊断任务信息
     * @Date:2019-06-24
     * @Return: List<DiagnosisPlanModel> 诊断任务信息集合
     * @Modified By:
     */
    @Override
    public List<DiagnosisPlanModel> getAllAutoDiagnosisPlan() {
        Map<String, Object> map = new HashMap<>();
        map.put("pType", ConstDefine.DIAGNOSIS_PLAN_AUTO);
        map.put("state", ConstDefine.STATE_ABLE);
        return diagnosisPlanMapper.getAllAutoDiagnosisPlan(map);
    }

    /**
     * @Author:cat
     * @Description 根据条件查询诊断任务详情
     * @params: id 主键ID
     * @params: createUser 创建人ID
     * @Date:2019-06-11
     * @Return: HaltModel 停机记录信息
     * @Modified By:
     */
    @Override
    public DiagnosisPlanModel getDiagnosisByIdCreateUser(Integer id, Integer createUser) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        map.put("createUser", createUser);
        map.put("pType", ConstDefine.DIAGNOSIS_PLAN_ARTIFICIAL);
        map.put("state", ConstDefine.STATE_ABLE);
        DiagnosisPlanModel diagnosisPlanModel = diagnosisPlanMapper.getDiagnosisByIdCreateUser(map);

        if (diagnosisPlanModel != null) {
            /** 查询诊断任务参数 */
            Map<String, Object> mapC = new HashMap<>();
            mapC.put("planId", diagnosisPlanModel.getId());
            List<DiagnosisParamModel> diagnosisParamModels = diagnosisParamMapper
                .getDiagnosisParamByDiagnosisId(mapC);

            diagnosisPlanModel.setDiagnosisParamModels(diagnosisParamModels);

            /** 查询诊断任务设备 */
            Map<String, Object> mapM = new HashMap<>();
            mapM.put("planId", diagnosisPlanModel.getId());
            mapM.put("state", ConstDefine.STATE_ABLE);
            mapM.put("halt", ConstDefine.HALT_NO);
            List<PlanCameraModel> planCameraModels = planCameraMapper
                .getPlanCameraByDiagnosisId(mapM);
            if (planCameraModels.size() > 0) {
                for (int i = 0; i < planCameraModels.size(); i++) {
                    if (planCameraModels.get(i).getGroupId() != null
                        && planCameraModels.get(i).getGroupId() != 0) {
                        String groupName = cameraGroupService
                            .getCameraGroupNameById(planCameraModels.get(i).getGroupId());
                        planCameraModels.get(i).setGroupName(groupName);
                    }
                }
            }
            diagnosisPlanModel.setPlanCameraModels(planCameraModels);
        }
        return diagnosisPlanModel;
    }

    /**
     * @Author:cat
     * @Description 新增自动诊断任务信息
     * @params: diagnosisPlanAddVO 诊断任务信息
     * @params: diagnosisParamAddVOS 诊断任务参数信息
     * @params: cameraIds 诊断任务设备ID
     * @Date:2019-06-24
     * @Return: Integer 主键
     * @Modified By:
     */
    @Override
    @Transactional
    public Integer addAutoDiagnosisPlan(DiagnosisPlanAddVO diagnosisPlanAddVO,
                                        List<DiagnosisParamAddVO> diagnosisParamAddVOS,
                                        String cameraIds) {
        /** 验证任务时间是否冲突 */

        List<DiagnosisPlanModel> Models = checkDiagnosisTime(diagnosisPlanAddVO.getStartTime(),
            diagnosisPlanAddVO.getEndTime(), diagnosisPlanAddVO.getExecuteType(),
            diagnosisPlanAddVO.getFlag(), 0);
        if (Models.size() > 0) {
            throw new ServiceException(
                StatusDefineMessage.GetMessage(StatusDefine.DIAGNOSIS_CONFLICTED));
        }

        /** 新增自动诊断任务信息 */
        diagnosisPlanAddVO.setPType(ConstDefine.DIAGNOSIS_PLAN_AUTO);
        int iRet = diagnosisPlanMapper.addAutoDiagnosisPlan(diagnosisPlanAddVO);

        if (iRet > 0) {
            /** 新增自动诊断任务参数信息 */
            for (int i = 0; i < diagnosisParamAddVOS.size(); i++) {
                diagnosisParamAddVOS.get(i).setPlanId(diagnosisPlanAddVO.getId());
                diagnosisParamMapper.addDiagnosisParam(diagnosisParamAddVOS.get(i));
            }

            /** 新增自动诊断任务设备信息 */
            if (!StringUtils.isBlank(cameraIds)) {
                String ids[] = cameraIds.split(",");

                for (int i = 0; i < ids.length; i++) {
                    PlanCameraModel planCameraModel = new PlanCameraModel();
                    planCameraModel.setPlanId(diagnosisPlanAddVO.getId());
                    planCameraModel.setCameraId(Integer.parseInt(ids[i]));
                    planCameraMapper.addPlanCamera(planCameraModel);
                }
            } else {
                throw new ServiceException(
                    StatusDefineMessage.GetMessage(StatusDefine.CAMERA_NULL));
            }
        }
        return diagnosisPlanAddVO.getId();
    }

    /**
     * @Author:cat
     * @Description 更新人工诊断任务信息
     * @params: pName 任务名称
     * @params: createUser 创建人ID
     * @params: cameraIds 设备ID
     * @params: diagnosisParamAddVOS 诊断任务参数集合
     * @params: isRun 是否执行：1是，2否
     * @Date:2019-06-24
     * @Return: Integer 影响行数
     * @Modified By:
     */
    @Override
    @Transactional
    public Integer updateArtificialDiagnosisPlan(String pName, Integer createUser, String cameraIds,
                                                 List<DiagnosisParamAddVO> diagnosisParamAddVOS,Integer isRun) {
        Integer planId = 0;
        /** 人工诊断任务信息是否存在 */
        Map<String, Object> map = new HashMap<>();
        map.put("createUser", createUser);
        map.put("pType", ConstDefine.DIAGNOSIS_PLAN_ARTIFICIAL);
        map.put("state", ConstDefine.STATE_ABLE);
        DiagnosisPlanModel diagnosisPlanModel = diagnosisPlanMapper.getDiagnosisByIdCreateUser(map);

        int iRet = 0;
        if (diagnosisPlanModel == null) {
            /** 新增人工诊断任务 */
            DiagnosisPlanAddVO diagnosisPlanAddVO = new DiagnosisPlanAddVO();
            diagnosisPlanAddVO.setPName(pName);
            diagnosisPlanAddVO.setPType(ConstDefine.DIAGNOSIS_PLAN_ARTIFICIAL);
            diagnosisPlanAddVO.setCreateUser(createUser);
            iRet = diagnosisPlanMapper.addArtificialDiagnosisPlan(diagnosisPlanAddVO);
            planId = diagnosisPlanAddVO.getId();
        } else {
            /** 修改人工诊断任务 */
            DiagnosisPlanEditVO diagnosisPlanEditVO = new DiagnosisPlanEditVO();
            diagnosisPlanEditVO.setId(diagnosisPlanModel.getId());
            diagnosisPlanEditVO.setPName(pName);
            diagnosisPlanEditVO.setPType(ConstDefine.DIAGNOSIS_PLAN_ARTIFICIAL);
            diagnosisPlanEditVO.setEditUser(createUser);
            diagnosisPlanEditVO.setState(ConstDefine.STATE_ABLE);
            iRet = diagnosisPlanMapper.updateArtificialDiagnosisPlan(diagnosisPlanEditVO);
            planId = diagnosisPlanEditVO.getId();

            /** 删除人工诊断任务参数信息 */
            Map<String, Object> mapDel = new HashMap<>();
            mapDel.put("planId", diagnosisPlanModel.getId());
            diagnosisParamMapper.deleteDiagnosisParam(mapDel);

            /** 删除人工诊断任务设备信息 */
            planCameraMapper.deletePlanCamera(mapDel);
        }

        if (iRet > 0) {
            /** 新增人工诊断任务参数信息 */
            for (int i = 0; i < diagnosisParamAddVOS.size(); i++) {
                diagnosisParamAddVOS.get(i).setPlanId(planId);
                diagnosisParamMapper.addDiagnosisParam(diagnosisParamAddVOS.get(i));
            }

            /** 新增人工诊断任务设备信息 */
            if (!StringUtils.isBlank(cameraIds)) {
                String ids[] = cameraIds.split(",");

                for (int i = 0; i < ids.length; i++) {
                    PlanCameraModel planCameraModel = new PlanCameraModel();
                    planCameraModel.setPlanId(planId);
                    planCameraModel.setCameraId(Integer.parseInt(ids[i]));
                    planCameraMapper.addPlanCamera(planCameraModel);
                }
            }

            /**是否立即执行任务*/
            if(isRun == ConstDefine.DIAGNOSIS_ISRUN_YES){
                addDiagnosisMQ(planId);
            }
        }
        return planId;
    }

    /**
     * @Author:cat
     * @Description 更新自动诊断任务信息
     * @params: diagnosisPlanEditVO 诊断任务信息
     * @params: diagnosisParamAddVOS 诊断任务参数信息
     * @params: cameraIds 诊断任务设备ID
     * @Date:2019-06-24
     * @Return: Integer 影响行数
     * @Modified By:
     */
    @Override
    @Transactional
    public Integer updateAutoDiagnosisPlan(DiagnosisPlanEditVO diagnosisPlanEditVO,
                                           List<DiagnosisParamAddVO> diagnosisParamAddVOS,
                                           String cameraIds) {
        /** 验证任务时间是否冲突 */
        List<DiagnosisPlanModel> Models = checkDiagnosisTime(diagnosisPlanEditVO.getStartTime(),
            diagnosisPlanEditVO.getEndTime(), diagnosisPlanEditVO.getExecuteType(),
            diagnosisPlanEditVO.getFlag(), diagnosisPlanEditVO.getId());
        if (Models.size() > 0) {
            throw new ServiceException(
                StatusDefineMessage.GetMessage(StatusDefine.DIAGNOSIS_CONFLICTED));
        }

        /** 修改自动诊断任务 */
        diagnosisPlanEditVO.setPType(ConstDefine.DIAGNOSIS_PLAN_AUTO);
        diagnosisPlanEditVO.setState(ConstDefine.STATE_ABLE);
        int iRet = diagnosisPlanMapper.updateAutoDiagnosisPlan(diagnosisPlanEditVO);

        if (iRet > 0) {
            /** 删除自动诊断任务参数信息 */
            Map<String, Object> mapDel = new HashMap<>();
            mapDel.put("planId", diagnosisPlanEditVO.getId());
            diagnosisParamMapper.deleteDiagnosisParam(mapDel);

            /** 删除自动诊断任务设备信息 */
            planCameraMapper.deletePlanCamera(mapDel);

            /** 新增自动诊断任务参数信息 */
            for (int i = 0; i < diagnosisParamAddVOS.size(); i++) {
                diagnosisParamAddVOS.get(i).setPlanId(diagnosisPlanEditVO.getId());
                diagnosisParamMapper.addDiagnosisParam(diagnosisParamAddVOS.get(i));
            }

            /** 新增自动诊断任务设备信息 */
            if (!StringUtils.isBlank(cameraIds)) {
                String ids[] = cameraIds.split(",");

                for (int i = 0; i < ids.length; i++) {
                    PlanCameraModel planCameraModel = new PlanCameraModel();
                    planCameraModel.setPlanId(diagnosisPlanEditVO.getId());
                    planCameraModel.setCameraId(Integer.parseInt(ids[i]));
                    planCameraMapper.addPlanCamera(planCameraModel);
                }
            } else {
                throw new ServiceException(
                    StatusDefineMessage.GetMessage(StatusDefine.CAMERA_NULL));
            }
        }
        return iRet;
    }

    /**
     * @Author:cat
     * @Description 删除自动诊断任务信息
     * @params: map 查询条件Map
     * @Date:2019-06-24
     * @Return: Integer 影响行数
     * @Modified By:
     */
    @Override
    public Integer deleteDiagnosisPlan(Map<String, Object> map) {
        /** 判断任务是否在进行中 */
        Map<String, Object> mapT = new HashMap<>();
        mapT.put("id", map.get("id"));
        mapT.put("state", ConstDefine.STATE_ABLE);
        DiagnosisPlanModel diagnosisPlanModel = diagnosisPlanMapper
            .getDiagnosisByIdCreateUser(mapT);
        if (diagnosisPlanModel.getIsOpen() == ConstDefine.DIAGNOSIS_IS_OPEN) {
            boolean bol = checkBetweenTime(diagnosisPlanModel.getStartTime(),
                diagnosisPlanModel.getEndTime());
            if (bol) {
                throw new ServiceException(
                    StatusDefineMessage.GetMessage(StatusDefine.DIAGNOSIS_RUNNING));
            }
        }

        return diagnosisPlanMapper.deleteDiagnosisPlan(map);
    }

    /**
     * @Author:cat
     * @Description 开启关闭自动诊断任务信息
     * @params: map 查询条件Map
     * @Date:2019-06-24
     * @Return: Integer 影响行数
     * @Modified By:
     */
    @Override
    public Integer updateAutoDiagnosisPlanIsOpen(Map<String, Object> map) {
        /** 判断任务是否在进行中 */
        Map<String, Object> mapT = new HashMap<>();
        mapT.put("id", map.get("id"));
        mapT.put("state", ConstDefine.STATE_ABLE);
        DiagnosisPlanModel diagnosisPlanModel = diagnosisPlanMapper
            .getDiagnosisByIdCreateUser(mapT);
        if (diagnosisPlanModel.getIsOpen() == ConstDefine.DIAGNOSIS_IS_OPEN) {
            boolean bol = checkBetweenTime(diagnosisPlanModel.getStartTime(),
                diagnosisPlanModel.getEndTime());
            if (bol) {
                throw new ServiceException(
                    StatusDefineMessage.GetMessage(StatusDefine.DIAGNOSIS_RUNNING));
            }
        }

        return diagnosisPlanMapper.updateAutoDiagnosisPlanIsOpen(map);
    }

    /**
     * @Author:cat
     * @Description 判断当前时间是否在两个时间范围内
     * @param startTime 开始时间 （8:00:00）
     * @param endTime 结束时间 （10:00:00）
     * @Date:2019-06-24
     * @Return: boolean true：在两个时间范围内
     * @Modified By:
     */
    private boolean checkBetweenTime(String startTime, String endTime) {
        Integer startNum = Integer.parseInt(startTime.split(":")[0]);
        Integer endNum = Integer.parseInt(endTime.split(":")[0]);

        SimpleDateFormat f = new SimpleDateFormat("HH");
        String hour = f.format(new Date());
        if (startNum <= Integer.parseInt(hour) && Integer.parseInt(hour) < endNum) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @Author:cat
     * @Description 验证要新增或修改的诊断任务时间是否与其他自动任务有冲突
     * @param startTime 开始时间 （8:00:00）
     * @param endTime 结束时间 （10:00:00）
     * @param executeType 执行周期：1每天，2每周，3每月
     * @param flag 周期数字
     * @param id 主键ID
     * @Date:2019-06-24
     * @Return: List<DiagnosisPlanModel> 冲突的任务集合
     * @Modified By:
     */
    private List<DiagnosisPlanModel> checkDiagnosisTime(String startTime, String endTime,
                                                        Integer executeType, Integer flag,
                                                        Integer id) {
        Integer startNum = Integer.parseInt(startTime.split(":")[0]);
        Integer endNum = Integer.parseInt(endTime.split(":")[0]);

        Map<String, Object> map = new HashMap<>();
        map.put("pType", ConstDefine.DIAGNOSIS_PLAN_AUTO);
        map.put("state", ConstDefine.STATE_ABLE);
        List<DiagnosisPlanModel> diagnosisPlanModels = diagnosisPlanMapper
            .getAllAutoDiagnosisPlan(map);

        /** 存放判断时间有冲突的任务 */
        List<DiagnosisPlanModel> Models = new ArrayList<>();

        for (int i = 0; i < diagnosisPlanModels.size(); i++) {
            if (!id.equals(diagnosisPlanModels.get(i).getId())) {
                /** 做验证的任务不是该任务本身 */
                Integer sta = Integer
                    .parseInt(diagnosisPlanModels.get(i).getStartTime().split(":")[0]);
                Integer end = Integer
                    .parseInt(diagnosisPlanModels.get(i).getEndTime().split(":")[0]);
                /** 判断时间冲突 */
                if ((sta <= startNum && startNum < end) || (sta < endNum && endNum <= end)) {
                    Models.add(diagnosisPlanModels.get(i));
                }
            }
        }

        /** 存放判断日期时间有冲突的任务 */
        List<DiagnosisPlanModel> DiagnosisModels = new ArrayList<>();
        if (Models.size() > 0) {
            /** 继续验证时间有冲突的任务日期是否冲突 */
            if (executeType == ConstDefine.DIAGNOSIS_EXECUTE_DAY) {
                /** 如果对比的任务执行周期为每天，任务一定冲突 */
                return Models;
            }
            for (int i = 0; i < Models.size(); i++) {
                if (Models.get(i).getExecuteType() == ConstDefine.DIAGNOSIS_EXECUTE_DAY) {
                    /** 如果对比的任务执行周期为每天，任务一定冲突 */
                    DiagnosisModels.add(Models.get(i));
                    continue;
                }
                if (executeType.equals(Models.get(i).getExecuteType())) {
                    /** 执行周期相同 */
                    if (flag.equals(Models.get(i).getFlag())) {
                        /** 执行周期数字也相同 */
                        DiagnosisModels.add(Models.get(i));
                        continue;
                    } else {
                        continue;
                    }
                }else {
                    /** 执行周期不同，任务一定冲突 */
                    DiagnosisModels.add(Models.get(i));
                    continue;
                }
            }
            return DiagnosisModels;
        } else {
            return Models;
        }
    }

    /**
     * @Author:cat
     * @Description 查询所有诊断队列任务
     * @Date:2019-06-25
     * @Return: List<diagnosisMQModel> 诊断任务信息集合
     * @Modified By:
     */
    @Override
    public List<DiagnosisMQModel> getDiagnosisMQ() {

        return diagnosisMQMapper.getDiagnosisMQ();
    }

    /**
     * @Author:cat
     * @Description 每小时查询是否有要执行的自动巡检任务
     * @Date:2019-06-25
     * @Modified By:
     */
    @Override
    public void getRunDiagnosis(){
        Map<String, Object> map = new HashMap<>();
        map.put("pType", ConstDefine.DIAGNOSIS_PLAN_AUTO);
        map.put("isOpen", ConstDefine.DIAGNOSIS_IS_OPEN);
        map.put("state", ConstDefine.STATE_ABLE);
        List<DiagnosisPlanModel> diagnosisPlanModels = diagnosisPlanMapper.getAllAutoDiagnosisPlan(map);
        if(diagnosisPlanModels.size()>0){
            for (int i = 0; i < diagnosisPlanModels.size(); i++) {
                Integer round = diagnosisPlanModels.get(i).getRound();//轮巡次数

                /**验证时间匹配*/
                Integer startNum = Integer.parseInt(diagnosisPlanModels.get(i).getStartTime().split(":")[0]);

                SimpleDateFormat f = new SimpleDateFormat("HH");
                String hour = f.format(new Date());
                if (startNum == Integer.parseInt(hour)) {
                    /**验证日期匹配*/
                    if(diagnosisPlanModels.get(i).getExecuteType() == ConstDefine.DIAGNOSIS_EXECUTE_DAY){
                        /**每天任务*/
                        /**根据轮巡次数添加队列任务*/
                        for (int j = 1; j <= round; j++) {
                            addDiagnosisMQ(diagnosisPlanModels.get(i).getId());
                        }
                    }
                    if(diagnosisPlanModels.get(i).getExecuteType() == ConstDefine.DIAGNOSIS_EXECUTE_WEEK){
                        /**每周任务*/
                        f = new SimpleDateFormat("E");
                        String weekStr = f.format(new Date());
                        if (diagnosisPlanModels.get(i).getFlag() == weekStrToNum(weekStr)) {
                            /**根据轮巡次数添加队列任务*/
                            for (int j = 1; j <= round; j++) {
                                addDiagnosisMQ(diagnosisPlanModels.get(i).getId());
                            }
                        }
                    }
                    if(diagnosisPlanModels.get(i).getExecuteType() == ConstDefine.DIAGNOSIS_EXECUTE_MONTH){
                        /**每月任务*/
                        f = new SimpleDateFormat("dd");
                        String day = f.format(new Date());
                        if (diagnosisPlanModels.get(i).getFlag() == Integer.parseInt(day)) {
                            /**根据轮巡次数添加队列任务*/
                            for (int j = 1; j <= round; j++) {
                                addDiagnosisMQ(diagnosisPlanModels.get(i).getId());
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @Author:cat
     * @Description 新增队列任务
     * @param planId 诊断任务ID
     * @Date:2019-06-25
     * @Return: Integer 影响行数
     * @Modified By:
     */
    private Integer addDiagnosisMQ(Integer planId) {
        Map<String, Object> map = new HashMap<>();
        map.put("planId", planId);
        return diagnosisMQMapper.addDiagnosisMQ(map);
    }

    /**
     * @Author:cat
     * @Description 星期中文转数字
     * @param weekStr 星期一、二、三、四、五、六、日
     * @Date:2019-06-25
     * @Return: Integer 1、2、3、4、5、6、7
     * @Modified By:
     */
    private Integer weekStrToNum(String weekStr) {
        switch (weekStr) {
            case "星期一":
                return 1;
            case "星期二":
                return 2;
            case "星期三":
                return 3;
            case "星期四":
                return 4;
            case "星期五":
                return 5;
            case "星期六":
                return 6;
            case "星期日":
                return 7;
            default:
                return 0;
        }
    }


}
